home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mntlib43 / mntlib / frexp.cpp < prev    next >
C/C++ Source or Header  |  1993-10-11  |  6KB  |  228 lines

  1. #if !defined (__M68881__) && !defined (sfp004)
  2. #
  3.  |-----------------------------------------------------------------------------
  4.  | remove exponent from floating point number
  5.  | C Interface
  6.  | double frexp(double value, int *eptr)
  7.  |
  8.  | returns significand (|significand| < 1)
  9.  |       in *eptr returns n such that value = significand * 2**n
  10.  |-----------------------------------------------------------------------------
  11.  | ported to 68000 by Kai-Uwe Bloem, 12/89
  12.  |  #1  original author: Peter S. Housel 9/21/88,01/17/89,03/19/89,5/24/89
  13.  |  #2    added support for denormalized numbers            -kub-, 01/90
  14.  |  #3  ported to gcc  ++jrb 04/90
  15.  |  #4  support for signed 0 - consistently with the rest - michal, 05/93
  16.  |      and some code cleanup
  17.  |-----------------------------------------------------------------------------
  18.  
  19. BIAS8    =    0x3ff - 1
  20.  
  21.     .text; .even
  22.     .globl _frexp
  23. _frexp:
  24.     movel    sp@(12),a0    | initialize exponent for loop
  25. #ifdef __MSHORT__
  26.     clrw    a0@
  27. #else
  28.     clrl    a0@
  29. #endif
  30.     lea    sp@(4),a1    | sp@(4) -> a1 - an address of value
  31. |                |   and a1@(8) - an address of *eptr
  32.     movel    a1@,d0        | keep value.sign
  33.     movel    d0,d1
  34.     bclr    #31,d1        | kill sign bit
  35.     tstl    d1        | 1st arg == 0 ?
  36.     bne    nonzero
  37.     tstl    a1@(4)
  38.     bne    nonzero
  39.     rts            | if 0 or -0 then d0 and d1 already set
  40. nonzero:
  41.     movel    d2,sp@-
  42. 2:                | return here when looping
  43.     swap    d0        | sign and exponent into lower 16 bits
  44.     movew    d0,d2        | set d2 for norm_df
  45.     bclr    #15,d0        | kill sign bit
  46.     lsrw    #4,d0
  47.  
  48.     cmpw    #BIAS8,d0    | get out of loop if finally (a1) in [0.5,1.0)
  49.     beq    3f
  50.  
  51.     moveq    #0x0f,d1    | remove exponent from value.mantissa
  52.     andb    d2,d1        | four upper bits of value in d1
  53.     bset    #4,d1        | implied leading 1
  54.     tstw    d0        | check for zero exponent
  55.     bne    1f
  56.     addqw    #1,d0
  57.     bclr    #4,d1        | nah, we do not need stinkin leadin 1
  58. 1:    movew    d1,a1@        | save results of our efforts
  59.  
  60.     movel    a1@,d1        | check for zero
  61.     orl    a1@(4),d1
  62.     beq    3f        | if zero, all done : exp = 0, num = 0.0
  63.                 | sign of zero is correct
  64.     subw    #BIAS8,d0    | remove bias
  65. #ifdef __MSHORT__
  66.     addw    d0,a0@        | add current exponent in
  67. #else
  68.     extl    d0
  69.     addl    d0,a0@        | add current exponent in
  70. #endif
  71.  
  72.     movew    #BIAS8,d0    | set bias for return value
  73.     clrw    d1        | rounding = 0
  74.     pea    L0        | call to norm_df (dirty, but dont ...
  75.     moveml    d2-d7,sp@-    | ... need to copy with -mshort)
  76.     moveml    a1@,d4-d5
  77.     jmp    norm_df        | normalize result
  78. L0:                | norm_df does not affect a0 or a1
  79. |                | but it pops d2-d7
  80.     moveml    d0-d1,a1@
  81.     bra    2b        | loop around to catch denormalized numbers
  82. 3:
  83.     moveml    a1@,d0-d1
  84.     movel    sp@+,d2
  85.                 | d0-d1 has normalized mantissa
  86.     rts
  87.  
  88. #endif    !__M68881__ && !sfp004
  89. #ifdef    __M68881__
  90.  
  91. |
  92. | remove exponent from floating point number
  93. | C Interface
  94. | double frexp(double value, int *eptr)
  95. |
  96. | returns significand (#significand# < 1)
  97. |       in *eptr returns n such that value = significand * 2**n
  98. |#######################################################################
  99. | hacked for the 68881 by Michael Ritzert, 5.10.90
  100. |#######################################################################
  101. | ported from sfp004 board to real 68881, mjr, August 1991
  102. |#######################################################################
  103. | a0:    pointer to n
  104. |     sp@(12) address of resulting exponent (n)
  105.  
  106.     .text; .even
  107.  
  108. .globl _frexp
  109.  
  110. _frexp:
  111.     moveal    a7@(12),a1        | address of n
  112.     fmoved    a7@(4),fp0        | load first_argument to fp0
  113.     fcmpd    #0r0.0,fp0        | 1st arg == 0 ?
  114.     fjeq    null_            | both parts of result are 0
  115.     fgetexpx fp0,fp1        | get expnent
  116.     fgetmanx fp0,fp0        | get mantissa
  117.     fscaleb #-1,fp0            |
  118. #ifdef __MSHORT__
  119.     fmovew    fp1,a1@            | fetch exp (fmovew from fp1)
  120.     addqw    #1,a1@            | correct result
  121. #else
  122.     fmovel    fp1,a1@            | fetch exp (fmovel from fp1)
  123.     addql    #1,a1@            | correct result
  124. #endif
  125.     fmoved    fp0,a7@-        | now fetch significand
  126.     moveml    a7@+,d0-d1
  127.     rts
  128. null_:
  129.     moveml    a7@(4),d0-d1
  130. #ifdef __MSHORT__
  131.     clrw    a1@
  132. #else
  133.     clrl    a1@
  134. #endif
  135.     rts
  136.  
  137. #endif    __M68881__
  138. #ifdef    sfp004
  139.  
  140. | remove exponent from floating point number
  141. | C Interface
  142. | double frexp(double value, int *eptr)
  143. |
  144. | returns significand (|significand| < 1)
  145. |       in *eptr returns n such that value = significand * 2**n
  146. |
  147. | hacked for the 68881 by Michael Ritzert, 5.10.90/18.12.91
  148. |
  149. | addresses of the 68881 data port. This choice is fastest when much data is
  150. | transferred between the two processors.
  151.  
  152. comm =     -6    |    fpu command reg
  153. resp =    -16    |    fpu response reg
  154. zahl =      0    |    fpu data reg
  155.  
  156. | a1:    fpu base register
  157. | a0:    pointer to n
  158. |     sp@(12) address of resulting exponent (n)
  159.  
  160. | waiting loop ...
  161. |
  162. | wait:
  163. | ww:    cmpiw    #0x8900,a0@(resp)
  164. |     beq    ww
  165. | is coded directly by
  166. |    .long    0x0c688900, 0xfff067f8                 (fpu base a1)
  167. | and
  168. | www:    tst.w    a0@(resp)
  169. |    bmi.b    www
  170. | is coded by
  171. |    .word    0x4a68,0xfff0,0x6bfa        | test
  172.  
  173.     .text; .even
  174.  
  175. .globl _frexp
  176.  
  177. _frexp:
  178.     tstl    sp@(4)        | 1st arg == 0 ?
  179.     bne    nonzero
  180.     tstl    sp@(8)
  181.     bne    nonzero
  182.     movel    sp@(12),a0
  183. #ifdef __MSHORT__
  184.     clrw    a0@
  185. #else
  186.     clrl    a0@
  187. #endif
  188.     clrl    d0
  189.     clrl    d1
  190.     rts
  191. nonzero:
  192.     lea    0xfffffa50:w,a0
  193.     movew    #0x5418,a0@(comm)    | load first argument to fp0
  194.     cmpiw    #0x8900,a0@(resp)    | check
  195.     movel    a7@(4),a0@
  196.     movel    a7@(8),a0@
  197.  
  198.     movew    #0x009f,a0@(comm)    | fgetman fp0,fp1
  199.     .word    0x4a68,0xfff0,0x6bfa    | test
  200.  
  201.     movew    #0x001e,a0@(comm)    | fgetexp fp0,fp0
  202.     moveal    a7@(12),a1        | address of n while the fpu is active
  203.     .word    0x4a68,0xfff0,0x6bfa    | test
  204.  
  205.     movew    #5026,a0@(comm)        | fscalew #-1,fp0
  206.     .long    0x0c688900, 0xfff067f8
  207.     movew    #-1,a0@
  208.  
  209. #ifdef __MSHORT__
  210.     movew    #0x7080,a0@(comm)    | fetch exp (fmovew from fp1)
  211.     .long    0x0c688900, 0xfff067f8
  212.     movew    a0@,a1@            | return exp
  213. #else
  214.     movew    #0x6080,a0@(comm)    | fetch exp (fmovel from fp1)
  215.     .long    0x0c688900, 0xfff067f8
  216.     movel    a0@,a1@            | return exp
  217. #endif
  218.     movew    #0x7400,a0@(comm)    | now fetch significand
  219.     .long    0x0c688900, 0xfff067f8
  220.     movel    a0@,d0
  221.     movel    a0@,d1
  222.     btst    #31,a7@(4)        | test sign of 1st arg
  223.     bge    fini            | arg neg ?
  224.     bset    #31,d0            | =>  negate result
  225. fini:    rts
  226.  
  227. #endif    sfp004
  228.